home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / progs / sviluppo / python-1.4 / lib / whrandom.py < prev    next >
Text File  |  1996-11-24  |  3KB  |  100 lines

  1. #    WICHMANN-HILL RANDOM NUMBER GENERATOR
  2. #
  3. #    Wichmann, B. A. & Hill, I. D. (1982)
  4. #    Algorithm AS 183: 
  5. #    An efficient and portable pseudo-random number generator
  6. #    Applied Statistics 31 (1982) 188-190
  7. #
  8. #    see also: 
  9. #        Correction to Algorithm AS 183
  10. #        Applied Statistics 33 (1984) 123  
  11. #
  12. #        McLeod, A. I. (1985)
  13. #        A remark on Algorithm AS 183 
  14. #        Applied Statistics 34 (1985),198-200
  15. #
  16. #
  17. #    USE:
  18. #    whrandom.random()    yields double precision random numbers 
  19. #                uniformly distributed between 0 and 1.
  20. #
  21. #    whrandom.seed(x, y, z)    must be called before whrandom.random()
  22. #                to seed the generator
  23. #
  24. #    There is also an interface to create multiple independent
  25. #    random generators, and to choose from other ranges.
  26.  
  27.  
  28. #    Translated by Guido van Rossum from C source provided by
  29. #    Adrian Baddeley.
  30.  
  31.  
  32. class whrandom:
  33.     #
  34.     # Initialize an instance.
  35.     # Without arguments, initialize from current time.
  36.     # With arguments (x, y, z), initialize from them.
  37.     #
  38.     def __init__(self, x = 0, y = 0, z = 0):
  39.         self.seed(x, y, z)
  40.     #
  41.     # Set the seed from (x, y, z).
  42.     # These must be integers in the range [0, 256).
  43.     #
  44.     def seed(self, x = 0, y = 0, z = 0):
  45.         if not type(x) == type(y) == type(z) == type(0):
  46.             raise TypeError, 'seeds must be integers'
  47.         if not 0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256:
  48.             raise ValueError, 'seeds must be in range(0, 256)'
  49.         if 0 == x == y == z:
  50.             # Initialize from current time
  51.             import time
  52.             t = long(time.time() * 256)
  53.             t = int((t&0xffffff) | (t>>24))
  54.             t, x = divmod(t, 256)
  55.             t, y = divmod(t, 256)
  56.             t, z = divmod(t, 256)
  57.         self._seed = (x, y, z)
  58.     #
  59.     # Get the next random number in the range [0.0, 1.0).
  60.     #
  61.     def random(self):
  62.         x, y, z = self._seed
  63.         #
  64.         x1, x2 = divmod(x, 177)
  65.         y1, y2 = divmod(y, 176)
  66.         z1, z2 = divmod(z, 178)
  67.         #
  68.         x = (171 * x2 -  2 * x1) % 30269
  69.         y = (172 * y2 - 35 * y1) % 30307
  70.         z = (170 * z2 - 63 * z1) % 30323
  71.         #
  72.         self._seed = x, y, z
  73.         #
  74.         return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
  75.     #
  76.     # Get a random number in the range [a, b).
  77.     #
  78.     def uniform(self, a, b):
  79.         return a + (b-a) * self.random()
  80.     #
  81.     # Get a random integer in the range [a, b] including both end points.
  82.     #
  83.     def randint(self, a, b):
  84.         return a + int(self.random() * (b+1-a))
  85.     #
  86.     # Choose a random element from a non-empty sequence.
  87.     #
  88.     def choice(self, seq):
  89.         return seq[int(self.random() * len(seq))]
  90.  
  91.  
  92. # Initialize from the current time
  93. #
  94. _inst = whrandom()
  95. seed = _inst.seed
  96. random = _inst.random
  97. uniform = _inst.uniform
  98. randint = _inst.randint
  99. choice = _inst.choice
  100.